package com.quanquan.store.service;

import DTO.PageDTO;
import DTO.user.UserInfoDTO;
import com.quanquan.store.dto.IdDTO;
import com.quanquan.store.dto.SendCouponRecordDTO;
import com.quanquan.store.entity.SendCouponRecord;
import com.quanquan.store.repository.SendCouponRecordRepository;
import com.quanquan.store.request.SendCouponRecordRequest;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cglib.core.internal.Function;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import utils.DateUtils;
import utils.StringUtil;

import javax.persistence.criteria.Predicate;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * @ClassName:SendCouponRecordService
 * @Description:TODO
 * @Author:xiongjunbao
 * @Date:2019/8/20 17:42
 * @Version 1.0
 */
@Service
public class SendCouponRecordService {

    private final SendCouponRecordRepository sendCouponRecordRepository;
    private final RestTemplate restTemplate;

    @Autowired
    public SendCouponRecordService(SendCouponRecordRepository sendCouponRecordRepository, RestTemplate restTemplate) {
        this.sendCouponRecordRepository = sendCouponRecordRepository;
        this.restTemplate = restTemplate;
    }


    public PageDTO<SendCouponRecordDTO> queryByCondition(SendCouponRecordRequest requestBody) {
        //分页
        Integer page = null == requestBody.getPage() ? 0 : requestBody.getPage();
        Integer size = null == requestBody.getSize() ? 10 : requestBody.getSize();
        //优惠券创建时间区间
        String fromDate = requestBody.getFromDate();
        String toDate = requestBody.getToDate();
        Integer status = requestBody.getStatus();
        //排序状态
        Sort sort = new Sort(Sort.Direction.DESC, "sendTime");
        //搜索关键词
        String keyword = requestBody.getKeyword();
        Pageable pageable = PageRequest.of(page, size, sort);
        Page<SendCouponRecord> paged = sendCouponRecordRepository.findAll((Specification<SendCouponRecord>) (root, query, criteriaBuilder) -> {
            List<Predicate> predicates = new ArrayList<>();
            // 创建具体查询条件
            if (null != status) {
                predicates.add(criteriaBuilder.equal(root.get("status").as(Integer.class), status));
            }
            if (StringUtil.isNotEmpty(fromDate)) {
                Date startOfDay = DateUtils.getStartOfDay(DateUtils.strToDate(fromDate, DateUtils.DATE));
                predicates.add(criteriaBuilder.greaterThanOrEqualTo(root.get("sendTime").as(Date.class), startOfDay));
            }
            if (StringUtil.isNotEmpty(toDate)) {
                Date endOfDay = DateUtils.getEndOfDay(DateUtils.strToDate(toDate, DateUtils.DATE));
                predicates.add(criteriaBuilder.lessThanOrEqualTo(root.get("sendTime").as(Date.class), endOfDay));
            }
            if (StringUtil.isNotEmpty(keyword)) {
                //查找关键字通过用户信息查询
                IdDTO idDTO = new IdDTO();
                idDTO.setKeyWord(keyword);
                UserInfoDTO userInfoDTO = restTemplate.postForObject("http://QUANQUAN-USER/user/query_keyword", idDTO, UserInfoDTO.class);
                if (userInfoDTO != null) {
                    List<DTO.user.UserDTO> users = userInfoDTO.getUserDTOS();
                    if (users.size() > 0) {
                        DTO.user.UserDTO userDTO = users.get(0);
                        predicates.add(criteriaBuilder.equal(root.get("userId").as(String.class), userDTO.getId()));
                    }
                }else {
                    Predicate p1 = criteriaBuilder.like(root.get("couponName").as(String.class), "%" + keyword + "%");
                    Predicate p2 = criteriaBuilder.or(criteriaBuilder.like(root.get("senderName").as(String.class), "%" + keyword + "%"), p1);
                    predicates.add(p1);
                }
            }

            return query.where(predicates.toArray(new Predicate[predicates.size()])).getRestriction();
        }, pageable);
        List<SendCouponRecord> sendCouponRecords = paged.getContent();

        List<String> userIds = sendCouponRecords.stream().filter(distinctByKey(SendCouponRecord::getUserId)).map(SendCouponRecord::getUserId).collect(Collectors.toList());

        List<SendCouponRecordDTO> sendCouponRecordDTOS = new LinkedList<>();
        for (SendCouponRecord sendCouponRecord : sendCouponRecords) {
            SendCouponRecordDTO sendCouponRecordDTO = new SendCouponRecordDTO();
            BeanUtils.copyProperties(sendCouponRecord, sendCouponRecordDTO);
            sendCouponRecordDTOS.add(sendCouponRecordDTO);
        }

        IdDTO idDTO = new IdDTO();
        idDTO.setForeignKeyIds(userIds);
        UserInfoDTO userInfoDTO = restTemplate.postForObject("http://QUANQUAN-USER/user/query_by_id_list", idDTO, UserInfoDTO.class);
        assert userInfoDTO != null;
        List<DTO.user.UserDTO> userDTOS = userInfoDTO.getUserDTOS();
        for (SendCouponRecordDTO sendCouponRecordDTO : sendCouponRecordDTOS) {
            for (DTO.user.UserDTO userDTO : userDTOS) {
                if (sendCouponRecordDTO.getUserId().equals(userDTO.getId())) {
                    sendCouponRecordDTO.setUserName(userDTO.getMemberName());
                    sendCouponRecordDTO.setPhone(userDTO.getPhone());
                }
            }
        }
        PageDTO<SendCouponRecordDTO> dto = new PageDTO<>();
        dto.setTotal(paged.getTotalElements());
        dto.setList(sendCouponRecordDTOS);
        dto.setPage(page);
        dto.setPageSize(size);
        dto.setKeyword(requestBody.getKeyword());
        dto.setTotalPage(paged.getTotalPages());
        dto.setFromDate(fromDate);
        dto.setToDate(toDate);
        return dto;
    }

    private static <T> java.util.function.Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
        Set<Object> seen = ConcurrentHashMap.newKeySet();
        return t -> seen.add(keyExtractor.apply(t));
    }


}
